#ifndef MOCHA_DETAIL_EVENTS_HPP_INCLUDED
#define MOCHA_DETAIL_EVENTS_HPP_INCLUDED

/**
 * @file 
 */

#include <cstdint>
#include "mocha/enum_string.hpp"
#include "mocha/memory.hpp"

namespace mocha {

namespace detail {
/**
 * 
 */
struct MOCHA_PACKED event_base {
	/// 
	std::int32_t type;
};
}

/**
 * Joystick button event.
 */
struct MOCHA_PACKED joy_button_event : public detail::event_base {
	/// Button state.
	std::int8_t state;
	/// Button index.
	std::int8_t button;
};
/**
 * Joystick hat (directional pad) event.
 */
struct MOCHA_PACKED joy_hat_event : public detail::event_base {
	/// Hat position. Either 1, 0, or -1.
	std::int8_t x, y;
};
/**
 * Joystick axis motion event.
 */
struct MOCHA_PACKED joy_motion_event : public detail::event_base {
	/// Axis index.
	std::int8_t axis;
	/// Coordinate of the axis ranging from the minimum to maximum signed 16-bit integer value.
	std::int16_t value;
};
/**
 * Keyboard event.
 */
struct MOCHA_PACKED key_event : public detail::event_base {
	/// Virtual key code.
	int key;
	/// Meta key mask.
	std::int8_t meta;
};
/**
 * Mouse button event.
 */
struct MOCHA_PACKED mouse_button_event : public detail::event_base {
	/// Button state.
	std::int8_t state;
	/// Button index.
	std::int8_t button;
	/// Pointer coordinates.
	int x, y;
};
/**
 * Mouse motion event.
 */
struct MOCHA_PACKED mouse_motion_event : public detail::event_base {
	/// Pointer coordinates.
	int x, y;
	/// Change in pointer coordinates (delta).
	int dx, dy;
};
/**
 * Quit event.
 * This event is very important, though it contains no data, and signals some external event that requests the termination of the application.
 */
struct MOCHA_PACKED quit_event : public detail::event_base {};
/**
 * User event.
 * May contain arbitrary (non-type-safe) data.
 * Typically inserted into the event queue manually.
 */
struct MOCHA_PACKED user_event : public detail::event_base {
	/// User event type. Can be used to identify the use or meaning of the event.
	int32_t user_type;
	/// Pointer to user data.
	void *user_data;
};
/**
 * Basic event.
 * Depending on the type, one of the members will be populated with sensible data. All other members should not be read.
 */
union MOCHA_PACKED mocha_event {
	int32_t type; // This member should match the memory location of the type member in all event structs.
	joy_button_event joy_button;
	joy_hat_event joy_hat;
	joy_motion_event joy_motion;
	key_event key;
	mouse_button_event mouse_button;
	mouse_motion_event mouse_motion;
	quit_event quit;
};
/**
 * Event types.
 */
enum event_type {
	event_joy_button_down = 1 << 0,
	event_joy_button_up = 1 << 1,
	event_joy_hat = 1 << 2,
	event_joy_motion = 1 << 3,
	event_key_down = 1 << 4,
	event_key_up = 1 << 5,
	event_mouse_button_down = 1 << 6,
	event_mouse_button_up = 1 << 7,
	event_mouse_motion = 1 << 8,
	event_quit = 1 << 9,
	event_user = 1 << 10,
	event_video_mode = 1 << 11
};
/**
 * Generalized event type masks. Useful for generating event filters.
 */
enum {
	event_joy_button = event_joy_button_down | event_joy_button_up,
	event_joy = event_joy_button | event_joy_hat | event_joy_motion,
	event_key = event_key_down | event_key_up,
	event_mouse_button = event_mouse_button_down | event_mouse_button_up,
	event_mouse = event_mouse_button | event_mouse_motion,
	event_video = event_video_mode
};
}
MOCHA_ENUM_STRING_BEGIN(mocha::event_type) {
	MOCHA_ENUM_STRING(event_joy_button_down);
	MOCHA_ENUM_STRING(event_joy_button_up);
	MOCHA_ENUM_STRING(event_joy_hat);
	MOCHA_ENUM_STRING(event_joy_motion);
	MOCHA_ENUM_STRING(event_key_down);
	MOCHA_ENUM_STRING(event_key_up);
	MOCHA_ENUM_STRING(event_mouse_button_down);
	MOCHA_ENUM_STRING(event_mouse_button_up);
	MOCHA_ENUM_STRING(event_mouse_motion);
	MOCHA_ENUM_STRING(event_quit);
	MOCHA_ENUM_STRING(event_video_mode);
} MOCHA_ENUM_STRING_END;

#endif

